package section6_3;

import java.util.Date;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

/**
 * Created by Hyman on 2017/6/12.
 *
 * 使用阻塞式线程安全列表 LinkedBlockingDeque
 *
 * 这个例子中使用了 LinkedBlockingDeque对象的两个方法，调用它们的线程可能会被阻塞，在阻塞时如果线程被中断，方法会抛出InterruptedException异常，所以必须捕获和处理这个异常。
 * LinkedBlockingDeqire类也提供了其他存取元素的方法，这些方法不会引起阻塞，而是抛出异常或返回null。
 * 　　♦ takeFirst()和takeLast():分别返回列表中第一个和最后一个元素，返回的元素会从列表中移除。如果列表为空，调用方法的线程将被阻塞直到列表中有可用的元素出现.
 * 　　♦ getFirst()和getLast():分别返回列表中第一个和最后一个元素，返回的元素不会从列表中移除。如果列表为空，则抛出NoSuchElementExcpetinon异常。
 * 　　♦ peek()、peekFirst()和peekLast():分别返回列表中第一个和最后一个元素，返回的元素不会从列表中移除。如果列表为空，返回null。
 * 　　♦ poll()、pollFirst()和pollLast():分别返回列表中第一个和最后一个元素，返回的元素将会从列表中移除。如果列表为空，返回null。
 * 　　♦ add()、addFirst()和addLast():分别将元素添加到列表中第一位和最后一位。如果列表已满(列表生成时指定了固定的容量),这些方法将抛出IllegalStateException异常。
 */
public class Main {

    public static void main(String[] args) throws Exception {

        LinkedBlockingDeque<String> list = new LinkedBlockingDeque<>();

        Client client = new Client(list);
        Thread thread = new Thread(client);
        thread.start();

        // 每300毫秒从列表中取出3个字符串对象
        for(int i=0; i<5; i++) {
            for (int j = 0; j < 3; j++) {
                String request = list.take();
                System.out.printf("Main: Request: %s at %s. Size: %d\n", request, new Date(), list.size());
            }
            TimeUnit.MILLISECONDS.sleep(300);
        }

        System.out.printf("Main: End of the program.\n");
    }

}
